import base64
import json
import os
import time
import uuid
from flask import make_response, jsonify, send_from_directory, url_for, request, current_app, send_file, Blueprint
from pathlib import Path

from insects_detection.project_utils import project_tools
from werkzeug.utils import secure_filename
from flask_restplus import Api, Resource

from utils.zipfile_utils import Myzip

view_files = Blueprint("view_files", __name__)
api = Api(view_files, version='1.0', title='File management API',
          description='在线文档目录服务')
ns = api.namespace('view_files', description='在线文档目录服务')


class file_manager_config():
    upload_folder_dir = project_tools.project_root_path() + os.sep + project_tools.insects_img_dirname
    project_root_dir = project_tools.project_root_path() + os.sep
    allowed_extensions = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif', 'zip', 'rar'])


# @ns.route("/ajax0/<path:fullname>/")
# class FileInfo(Resource):
#     def get(self,fullname):
#         fullname = f'/{fullname}'
#         position = int(request.args.get('position'))
#         current_app.logger.debug(position)
#         # if os.path.isfile(full_name):
#         #     fo = open(full_name,encoding='utf8')
#         #     content  = fo.read()
#         #     return content
#         # else :
#         #     return "There is no log file"
#
#         with open(fullname, 'rb') as f:
#             try:
#                 if position == 0:
#                     f.seek(-50000, 2)
#                 else:
#                     f.seek(position, 0)
#             except Exception:
#                 current_app.logger.exception('读取错误')
#                 f.seek(0, 0)
#             content_text = f.read().decode()
#             # nb_print([content_text])
#             content_text = content_text.replace('\n', '<br>')
#             # nb_print(content_text)
#             position_new = f.tell()
#             current_app.logger.debug(position_new)
#             # nb_print(len(content_text))
#             return jsonify(content_text=content_text, position=position_new)

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1] in file_manager_config.allowed_extensions


@ns.route('/upload/', '/upload/<path:upload_dir>', methods=['POST'])
class Upload(Resource):
    def post(self, upload_dir='default_path'):
        '''
        上传文件至当前打开的服务器端的文件目录
        :param upload_dir:
        :return: 上传成功与否以及上传的文件名
        '''
        # Get the name of the uploaded files
        uploaded_files = request.files.getlist("file")
        filenames = []
        filepath = ''
        # if project_tools.system_platform == 'linux' and upload_dir != 'default_path':
        #     upload_dir = os.sep + upload_dir
        #     print("upload_dir is: ", upload_dir)
        if upload_dir != 'default_path':
            upload_dir = upload_dir.replace("/", os.sep)
            upload_dir += (os.sep + str(uuid.uuid4()))
            if os.path.exists(upload_dir) is False:
                os.mkdir(upload_dir)
        for index, file in enumerate(uploaded_files):
            # Check if the file is one of the allowed types/extensions
            if file:
            # if file and allowed_file(file.filename):
                # Make the filename safe, remove unsupported chars
                filename = secure_filename(file.filename)
                # Move the file form the temporal folder to the upload
                # folder we setup
                if upload_dir != 'default_path':
                    filename = str(index) + '.jpeg'
                    file.save(os.path.join(file_manager_config.project_root_dir + upload_dir, filename))
                    filepath = file_manager_config.project_root_dir + upload_dir
                else:
                    file.save(os.path.join(file_manager_config.upload_folder_dir, filename))
                    filepath = file_manager_config.upload_folder_dir
                filenames.append(filename)
        # if filepath.endswith("/"):
            # filepath = filepath
        # return render_template('upload.html', filenames=filenames)
        if filepath.endswith(os.sep) is False:
            filepath += os.sep
        return make_response(jsonify({'code': 20000, 'message': 'ok',
                                      'data': {'filenames': filenames, 'filepath': filepath}}), 200)


# @ns.route('/uploads/<filename>')
# class UploadFile(Resource):
#     def get(self, filename):
#         return send_from_directory(file_manager_config.upload_folder_dir,
#                             filename)


@ns.route('/scan/', '/scan/<path:logs_dir>', endpoint='index')
class Index(Resource):
    def get(self, logs_dir=project_tools.project_root_path()):
        '''
        获取当前路径下的所有文件信息
        :param logs_dir:
        :return: 返回所有程序允许的文件类型详细信息，is_dir（是否为目录），filesize（文件大小），last_modified_time(上次修改时间)，
        url（文件访问路径），download_url（文件下载路径），fullname（绝对路径），filename（文件名），filetype（文件类型）
        '''
        # current_app.logger.debug(logs_dir)
        current_platform = project_tools.get_system_platform()
        file_ele_list = list()
        dir_ele_list = list()
        for f in (Path('/') / Path(logs_dir)).iterdir():
            fullname = str(f).replace('\\', '/')
            fullname = fullname[1:] if current_platform == 'linux' else fullname
            if f.is_file():
                if f.suffix in project_tools.supported_filetype:
                    # current_app.logger.debug(str(f).replace('\\', '/')[1:])
                    # current_app.logger.debug((logs_dir, str(f).replace('\\','/')[1:]))
                    # current_app.logger.debug(str(f))
                    # current_app.logger.debug(url_for('download_file', fullname=fullname[0:]))
                    # current_app.logger.debug(url_for('download_file', logs_dir='', filename='windows_to_linux_syn_config.json'))
                    file_ele_list.append({'is_dir': 0, 'filesize': project_tools.convert_file_size(os.path.getsize(f)),
                                          'last_modify_time': time.strftime('%Y-%m-%d %H:%M:%S',
                                                                            time.localtime(os.stat(f).st_mtime)),
                                          'url': url_for('index', logs_dir=fullname),
                                          'download_url': url_for('download_file', fullname=fullname),
                                          'fullname': fullname,
                                          'filename': f.name,
                                          'filetype': f.suffix[1:].upper()})
            if f.is_dir():
                dir_ele_list.append({'is_dir': 1, 'filesize': "0 K",
                                     'last_modify_time': time.strftime('%Y-%m-%d %H:%M:%S',
                                                                       time.localtime(os.stat(f).st_mtime)),
                                     'url': url_for('index', logs_dir=fullname),
                                     'download_url': url_for('download_file', fullname=fullname),
                                     'fullname': fullname,
                                     'filename': fullname.rsplit('/', 1)[1],
                                     'filetype': '文件夹'})
        # return render_template('dir_view.html', ele_list=dir_ele_list + file_ele_list, logs_dir=logs_dir)
        return make_response(jsonify(
            {'code': 20000, 'message': 'ok', 'data': {'ele_list': dir_ele_list + file_ele_list, 'logs_dir': logs_dir}}),
            200)


@ns.route('/download/', '/download/<path:fullname>', endpoint='download_file')
class Download(Resource):
    def get(self, fullname=''):
        '''
        文件下载
        :param fullname:
        :return: 下载文件或在线预览
        '''
        if project_tools.system_platform == 'linux':
            fullname = os.sep + fullname
        # current_app.logger.debug(fullname)
        return send_file(f'{fullname}')
        # return send_from_directory(f'/{logs_dir}',
        #                            filename, as_attachment=True, )


@ns.route('/get_base64_image/<path:image_path>')
class GetBase64Image(Resource):
    def get(self, image_path):
        if project_tools.system_platform == 'linux':
            image_path = os.sep + image_path
        if os.path.exists(image_path):
            with open(image_path, 'rb') as f:
                res = base64.b64encode(f.read()).decode()
            response = make_response(jsonify({'code': 20000, 'message': 'ok', 'data': res}), 200)
        else:
            response = make_response(jsonify({'code': 20000, 'message': 'image does not exist!', 'data': ''}), 200)
        return response


@ns.route('/unzip_file/<path:file_dest_path>')
class UnzipFile(Resource):
    def get(self, file_dest_path):
        if project_tools.system_platform == 'linux':
            file_dest_path = os.sep + file_dest_path
        paths = file_dest_path.split('-')
        file_path = paths[0]
        destination = paths[1]
        myzip = Myzip(file_path)
        message, status = myzip.unzip_file(destination)
        response = make_response(jsonify({'code': 20000, 'message': message, 'data': {'status': status}}), 200)
        return response


# 显示当前目录路径
# output:以"/"分割的路径数组
# logs_dir=project_tools.project_root_path()
@ns.route('/current_dir/', '/current_dir/<path:logs_dir>', endpoint='current_dir')
class CurrentDir(Resource):
    def get(self, logs_dir=''):
        '''
        获取当前文件绝对路径，用于前端“面包屑”控件
        :param logs_dir:
        :return: 从当前文件开始所有的父级目录，以列表形式存储
        '''

        current_platform = 'linux'
        if logs_dir == '':
            if current_platform == 'windows':
                logs_dir = project_tools.project_root_path()
            else:
                logs_dir = project_tools.project_root_path()[1:]

        parent_dir_list = list()
        pa = Path(f'/{logs_dir}')
        if current_platform == 'windows':
            while True:
                parent_dir_list.append({'to_url': pa.as_posix()[1:], 'dir_name': pa.name[:]})
                pa = pa.parent
                if pa == Path('/'):
                    parent_dir_list.append({'to_url': url_for('index', logs_dir=''), 'dir_name': '根目录'})
                    break
            parent_dir_list.reverse()
            response = make_response(jsonify(
                {'code': 20000, 'message': 'ok', 'data': {'parent_dir_list': parent_dir_list, 'logs_dir': logs_dir}}),
                200)
        else:
            while True:
                parent_dir_list.append({'to_url': str(pa)[1:], 'dir_name': pa.name[:]})
                pa = pa.parent
                if pa == Path('/'):
                    parent_dir_list.append({'to_url': url_for('index', logs_dir=''), 'dir_name': '根目录'})
                    break
            parent_dir_list.reverse()
            response = make_response(jsonify(
                {'code': 20000, 'message': 'ok', 'data': {'parent_dir_list': parent_dir_list, 'logs_dir': logs_dir}}),
                200)
        return response


#
@ns.route('/delete_file/', '/delete_file/<path:remove_path>', endpoint='delete_file')
class DeleteFile(Resource):
    def get(self, remove_path='not_specified'):
        '''
        删除指定文件
        :param remove_path:
        :return: 删除文件操作是否成功信息
        '''
        if remove_path == 'not_specified':
            return make_response(
                jsonify({'code': 20000, 'message': 'ok', 'data': {'delete_stat': 'Illegal file path'}}), 400)
        if project_tools.system_platform == 'linux':
            remove_path = os.sep + remove_path
        if os.path.exists(remove_path):  # 如果文件存在
            # 删除文件，可使用以下两种方法。
            os.remove(remove_path)  # 则删除
            delete_stat = 'ok'
            # os.unlink(remove_dir)
        else:
            delete_stat = 'fail'
        return make_response(jsonify({'code': 20000, 'message': 'ok', 'data': {'delete_stat': delete_stat}}), 200)
